using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using FrameWork.Source.Animation_Classes;
using FrameWork.Source.Texture;

namespace FrameWork.Source.Object_Classes
{
    class CAnimatedObject : CObject
    {
        /// <summary>
        /// Get or set velocity of this animated object
        /// </summary>
        public Vector2 m_vec2Velocity { get; set; }


        /// <summary>
        /// An array holding animation information of this animated object
        /// </summary>
        private CAnimation[] m_pAnimation;

        /// <summary>
        /// Number frame this animated object has. Default : 1 frame
        /// </summary>
        private int m_iNumFrame;

        /// <summary>
        /// Number frame in one row this animated object has. Default : 1 frame
        /// </summary>
        private int m_iNumFrameInRow;

        /// <summary>
        /// Current animation this animated object is playing
        /// </summary>
        private int m_iCurrAnim;

        /// <summary>
        /// Get or set gravity for this object. Default : 800.0f
        /// </summary>
        public float m_fGravity { get; set; }

        /// <summary>
        /// Get or set friction for this object
        /// </summary>
        public float m_fFriction { get; set; }

        /// <summary>
        /// Source rect of this animated object image
        /// </summary>
        protected Rectangle m_recSource;

        /// <summary>
        /// Contructor of this class
        /// </summary>
        public CAnimatedObject() : base()
        {
            m_vec2Velocity = Vector2.Zero;
            m_pAnimation = null;
            m_iCurrAnim = 0;
            m_iNumFrame = 1;
            m_iNumFrameInRow = 1;
            m_fFriction = 100.0f;
            m_fGravity = 800.0f;
        }

        /// <summary>
        /// Load information to create sprite animation for this animated object
        /// Note : This override use to create object has >= 2 animation
        /// </summary>
        /// <param name="pImage">A pointer to the texture image for this object</param>
        /// <param name="numFrame">Total frame of this animated object</param>
        /// <param name="numFrameInRow">Number frame in one row</param>
        /// <param name="frameWidth">Width of this object ( one frame )</param>
        /// <param name="frameHeight">Height of this object ( one frame )</param>
        /// <param name="pAnimation">An array holding the animation information</param>
        public void loadSprite(CTexture pImage, int numFrame, int numFrameInRow, int frameWidth , int frameHeight , CAnimation[] pAnimation)
        {
            setImage(pImage, frameWidth, frameHeight);
            m_iNumFrame = numFrame;
            m_iNumFrameInRow = numFrameInRow;
            m_pAnimation = pAnimation;
            changeAnimation(0);
        }


        /// <summary>
        /// Load information to create sprite animation for this animated object
        /// Note : This override use to create object has only 1 animation
        /// </summary>
        /// <param name="pImage">A pointer to the texture image for this object</param>
        /// <param name="numFrame">Total frame of this animated object</param>
        /// <param name="numFrameInRow">Number frame in one row</param>
        /// <param name="frameWidth">Width of this object ( one frame )</param>
        /// <param name="frameHeight">Height of this object ( one frame )</param>
        /// <param name="pAnimation">The animation information</param>
        public void loadSprite(CTexture pImage, int numFrame, int numFrameInRow, int frameWidth, int frameHeight , CAnimation pAnimation)
        {
            setImage(pImage, frameWidth, frameHeight);
            m_iNumFrame = numFrame;
            m_iNumFrameInRow = numFrameInRow;
            m_pAnimation = new CAnimation[1];
            m_pAnimation[0] = pAnimation;
            changeAnimation(0);
        }


        /// <summary>
        /// Change to next animation
        /// </summary>
        /// <param name="nextAnimIndex">Next animation index</param>
        public void changeAnimation(int nextAnimIndex)
        {
            if (m_pAnimation == null)
                return;
            if (nextAnimIndex >= m_pAnimation.Length)
                return;
            if (m_pSprite == null)
                return;
            m_iCurrAnim = nextAnimIndex;
            //m_pAnimation[m_iCurrAnim].m_iCurrFrame = m_pAnimation[m_iCurrAnim].m_iStartFrame;
            m_pAnimation[m_iCurrAnim].updateSourceRect(ref m_recSource, m_iFrameWidth, m_iFrameHeight, m_iNumFrameInRow);
        }

        /// <summary>
        /// Change to next animation
        /// </summary>
        /// <param name="animationName">Next animation name</param>
        public void changeAnimation(string animationName)
        {
            int count = m_pAnimation.Length;
            for (int i = 0; i < count; ++i)
            {
                if (m_pAnimation[i].m_strName == animationName)
                {
                    m_iCurrAnim = i;
                    //m_pAnimation[m_iCurrAnim].m_iCurrFrame = m_pAnimation[m_iCurrAnim].m_iStartFrame;
                    m_pAnimation[m_iCurrAnim].updateSourceRect(ref m_recSource, m_iFrameWidth, m_iFrameHeight, m_iNumFrameInRow);
                    return;
                }
            }
        }



        /// <summary>
        /// Update our object
        /// </summary>
        /// <param name="deltaTime"></param>
        public override void update(float deltaTime)
        {
            updateAnimation(deltaTime);
        }


        /// <summary>
        /// Update our animation
        /// </summary>
        /// <param name="deltaTime"></param>
        protected void updateAnimation(float deltaTime)
        {
            if (m_pAnimation != null)
                m_pAnimation[m_iCurrAnim].update(deltaTime, ref m_recSource, m_iFrameWidth, m_iFrameHeight, m_iNumFrameInRow);
        }


        /// <summary>
        /// Get animation based on input index
        /// </summary>
        /// <param name="index">Index of animation we want to get</param>
        /// <returns>Animation we want to get</returns>
        public CAnimation getAnimation(int index)
        {
            if (index >= m_pAnimation.Length)
                return null;

            return m_pAnimation[index];
        }


        /// <summary>
        /// Get animation based on input name
        /// </summary>
        /// <param name="name">Name of animation we want to get</param>
        /// <returns>Animation we want to get</returns>
        public CAnimation getAnimation(string name)
        {
            int count = m_pAnimation.Length;
            for (int i = 0; i < count; ++i)
            {
                if (m_pAnimation[i].m_strName == name)
                {
                    return m_pAnimation[i];
                }
            }

            return null;
        }

        /// <summary>
        /// Get current animation is playing
        /// </summary>
        /// <returns>Current animation</returns>
        public CAnimation getCurrAnimation()
        {
            return getAnimation(m_iCurrAnim);
        }

        /// <summary>
        /// Draw this object into screen
        /// </summary>
        public override void draw()
        {
            if (m_isVisible)
                m_pSprite.draw(m_vec2Position, m_fDeep, m_recSource);
        }

        /// <summary>
        /// Get bounding box of this animated object
        /// </summary>
        /// <returns>Bound box of this object</returns>
        public override Rectangle getBoundBox()
        {
            return base.getBoundBox();
        }

        /// <summary>
        /// Coolision checking with other object
        /// </summary>
        /// <param name="pObj">Other object that this animated object collide with</param>
        /// <returns>true if collide , false if not</returns>
        public override bool Collision(ref CObject pObj)
        {
            return base.Collision(ref pObj);
        }
    }
}
